#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

int main(int argc, char **argv) {
    cv::Mat src = cv::imread("/home/xlll/Downloads/opencv/samples/data/LinuxLogo.jpg", cv::IMREAD_COLOR);
    if (src.empty()) {
        std::cout << "Failed to read image" << std::endl;
        return EXIT_FAILURE;
    }
    
    cv::Mat gray;
    cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    cv::Mat binary;
    cv::threshold(gray, binary, 128, 255, cv::THRESH_BINARY);
    
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    cv::findContours(binary, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
    if (contours.size() < 1) {
        return EXIT_FAILURE;
    }
    for (int i = 3; i < contours.size(); i++) {
        cv::drawContours(src, contours, i, cv::Scalar(255, 255, 0), 2);
        std::cout << "Contour " << i << std::endl;
        
        cv::Moments moments = cv::moments(contours[i]);
        double cx = moments.m10 / moments.m00;
        double cy = moments.m01 / moments.m00;
        std::cout << "\tCentroid = (" << cx << ", " << cy << ")" << std::endl;
        
        cv::Rect rect = cv::boundingRect(contours[i]);
        double aspectRatio = (double)rect.width / rect.height;
        std::cout << "\tAspect Ratio = " << aspectRatio << std::endl;
        
        double area = cv::contourArea(contours[i]);
        double extent = area / (rect.width * rect.height);
        std::cout << "\tExtent = " << extent << std::endl;
        
        std::vector<cv::Point> hull;
        cv::convexHull(contours[i], hull);
        double hullArea = cv::contourArea(hull);
        double solidity = area / hullArea;
        std::cout << "\tSolidity = " << solidity << std::endl;
        
        double equivalentDiameter = std::sqrt(4 * area / CV_PI);
        std::cout << "\tEquivalent Diameter = " << equivalentDiameter << std::endl;
        
        cv::RotatedRect rotatedRect;
        rotatedRect = cv::fitEllipse(contours[i]);
        double orientation = rotatedRect.angle;
        std::cout << "\tOrientation = " << orientation << std::endl;
        
        double m20 = moments.m20;
        double m02 = moments.m02;
        double m11 = moments.m11;
        double ecentricity = (m20+m02+std::sqrt((m20-m02)*(m20-m02)+4*m11*m11)) / (m20+m02-std::sqrt((m20-m02)*(m20-m02)+4*m11*m11));
        std::cout << "\tEcentricity = " << ecentricity << std::endl;
        
        double perimeter = cv::arcLength(contours[i], true);
        std::cout << "\tPerimeter = " << perimeter << std::endl;
        
        double circularity = 4.0 * CV_PI * area / (perimeter * perimeter);
        std::cout << "\tCircularity = " << circularity << std::endl;
        
        std::cout << "=================================================" << std::endl;
    }
    
    cv::imshow("result", src);
    cv::waitKey(0);
    
    return 0;
}
